/**
 * Created with IntelliJ IDEA.
 * Date: 19.09.13
 * Time: 22:30
 */
package module1.palindromes;

import java.util.Scanner;

/**
 * The Class Palindrome provides searching palindromes (substrings) with min length 3 in string readout from console
 * Space is considered as symbol, so {a a}, { abba }, etc. are palindromes
 * Substring with same characters but different indexes (positions in string) are considered as two different palindromes:
 * In string {bbbb} are 3 palindromes: {bbbb}, {bbb}, {bbb} - last 2 have different indexes
 *
 * @author Anzhela Petrovska
 */
public class Palindrome {
    private static final int MIN_LENGTH = 3;
    private static final int ARRAY_LENGTH = 1000;

    /**
     * Main method:  invocation of startMenu() method
     */
    public static void main(String[] args) {
        startMenu();
    }

    /**
     * The method is used to check what action user want to do: exit program or see menu options
     * Allows re-input data when input errors occurs without re-start of program
     */
    private static void startMenu() {
        System.out.println("\nEnter:\nexit the program  - 0\nsee menu options  - any other key\n______________________________\n");
        Scanner scanner = new Scanner(System.in);

        String exitOption = scanner.nextLine();

        while (!exitOption.equals("0")) {
            doMenuOptionActions();
        }
    }

    /**
     * The method used to choice desired action from menu: exit or continue
     * Case structure allows future modifications and additions for the doMenuOptionActions
     */
    private static void doMenuOptionActions() {
        int menuOptionId = getMenuOptionId();

        switch (menuOptionId) {
            case 1:
                String string = getInputString();
                String[] palindromesArray = findPalindromes(string);
                printPalindromes(palindromesArray);
                break;
            case 0:
                System.out.println("EXIT...");
                System.exit(0);
                break;
            default:
                System.out.println("No such id of action");
        }
    }

    /**
     * The method used to get input data (optionId) for method doMenuOptionActions()
     * Functional description:
     * - user must enter numeric value
     * - in other case,appears error message
     * - possibility of re-input data without exit or re-start program
     *
     * @return int value
     */
    private static int getMenuOptionId() {
        System.out.println("\nOptions:\n0 - for exit\n1 - to check string for palindromes");
        Scanner scanner = new Scanner(System.in);
        int optionId = -1;

        if (scanner.hasNextInt()) {
            optionId = scanner.nextInt();
        } else {
            System.out.println("ERROR! It is not a correct value");
            startMenu();
        }

        return optionId;
    }

    /**
     * The method used for getting a string from the console and invocation method for checking length string
     */
    private static String getInputString() {
        System.out.println("Enter string, min length is 3 characters");
        Scanner scanner = new Scanner(System.in);
        String inputString = scanner.nextLine();
        int stringLength = getLength(inputString);

        checkStringLength(stringLength);

        return inputString;
    }

    private static int getLength(String string) {
        return string.length();
    }

    /**
     * The method used for verification the length of the string
     *
     * @return true if input string has 3 or more symbols
     */
    private static boolean checkStringLength(int length) {
        if (length < MIN_LENGTH) {
            System.out.println("ERROR! It is not a correct input string");
            startMenu();
            return false;
        }
        return true;
    }

    /**
     * The method used for determining whether a substring is a palindrome
     *
     * @param str    - substring for verification is it a palindrome
     * @param length - length of verifiable substring
     * @return boolean value of verification
     */
    private static boolean isPalindrome(String str, int length) {
        for (int position = 0; position < length / 2; position++) {
            if (str.charAt(position) != str.charAt(length - position - 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * The method used for searching palindromes in input string
     */
    private static String[] findPalindromes(String str) {
        String[] palindromesArray = new String[ARRAY_LENGTH];
        int length = getLength(str);
        int palindromesCounter = 0;

        for (int startIndex = 0; startIndex <= length - MIN_LENGTH; startIndex++)
            for (int endIndex = startIndex + MIN_LENGTH; endIndex <= length; endIndex++) {
                String subString = str.substring(startIndex, endIndex);
                if (isPalindrome(subString, subString.length())) {
                    palindromesArray[palindromesCounter] = subString;
                    palindromesCounter++;
                }
            }
        return palindromesArray;
    }

    /**
     * The method used for printing info: array of founded palindromes and quantity of it
     *
     * @param palindromes - array of founded palindromes
     */
    private static void printPalindromes(String[] palindromes) {
        int elementIndex = 0;

        while (palindromes[elementIndex] != null) {
            System.out.format("Substring {%s} is palindrome\n", palindromes[elementIndex]);
            elementIndex++;
        }
        System.out.format("\nThere are %d palindromes in input string\n", elementIndex);
    }
}